#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;

int T, n, m, L, V, d, v, a, p[N];

int ss;
struct node {
    int lft, rgt;
    bool able;
    bool friend operator < (node x, node y) {
        return x.rgt < y.rgt;
    }
} s[N];

struct nodes {
    int lft[N << 2], rgt[N << 2];
    bool sum[N << 2];
    void build(int x, int l, int r) {
        lft[x] = l, rgt[x] = r, sum[x] = 0;
        if (l == r)
            return;
        int mid = l + r >> 1;
        build(x << 1, l, mid);
        build((x << 1) | 1, mid + 1, r);
    }
    bool query(int x, int l, int r) {
        if (l <= lft[x] && r >= rgt[x])
            return sum[x];
        int mid = lft[x] + rgt[x] >> 1;
        bool tmp = 0;
        if (l <= mid)
            tmp |= query(x << 1, l, r);
        if (r > mid)
            tmp |= query((x << 1) | 1, l, r);
        return tmp;
    }
    void add(int x, int l) {
        sum[x] = 1;
        if (l == lft[x] && l == rgt[x])
            return;
        int mid = lft[x] + rgt[x] >> 1;
        if (l <= mid)
            add(x << 1, l);
        if (l > mid)
            add((x << 1) | 1, l);
    }
} tree, tre;

int main() {
    freopen("detect.in", "r", stdin);
    freopen("detect.out", "w", stdout);
    scanf("%d", &T);
    while (T--) {
		scanf("%d%d%d%d", &n, &m, &L, &V);
        ss = 0;
        for (int i = 0; i < n; i++) {
			scanf("%d%d%d", &d, &v, &a);
            if (a == 0) {
                if (v > V)
                    s[ss++] = {d, L, 0};
                continue;
            }
            if (a > 0) {
                int lim = (V * V - v * v + 2 * a - 1) / (2 * a) + d + 1;
                if (v > V)
                    lim = d;
                if (lim <= L)
                    s[ss++] = {lim, L, 0};
            }
            if (a < 0) {
                int lim = (V * V - v * v + 2 * a + 1) / (2 * a) + d - 1;
                if (v < V)
                    lim = -1;
                lim = min(lim, L);
                if (lim >= d)
                    s[ss++] = {d, lim, 0};
            }
        }
        // for (int i = 0; i < ss; i++)
        //     cout << i << ':' << s[i].lft << ',' << s[i].rgt << endl;
        tree.build(1, 0, L);
        for (int j = 0; j < m; j++) {
			scanf("%d", &p[j]);
            tree.add(1, p[j]);
        }
        sort(p, p + m);
        int ans = 0;
        for (int i = 0; i < ss; i++)
            if (tree.query(1, s[i].lft, s[i].rgt)) {
                ans++;
                s[i].able = 1;
            }
        printf("%d ", ans);
        sort(s, s + ss);
        int i = 0, j = 0;
        ans = 0;
        tre.build(1, 0, L);
        while (i < ss && j < m) {
            while (i < ss && (s[i].able == 0 || tre.query(1, s[i].lft, s[i].rgt) == 1))
                i++;
            if (i == ss)
                break;
            while (j < m && p[j] <= s[i].rgt)
                j++;
            j--, ans++;
            tre.add(1, p[j]);
        }
        printf("%d\n", m - ans);
    }
    return 0;
}
